package com.perceptivesoftware.licensing.server.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.perceptivesoftware.licensing.client.common.util.NPAction;
import com.perceptivesoftware.licensing.client.common.util.NPType;
import com.perceptivesoftware.licensing.client.common.util.PerceptivePermission;
import com.perceptivesoftware.licensing.client.common.util.PerceptivePermissions;
import com.perceptivesoftware.licensing.client.common.util.Utils;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.plugin.role.RoleNavItem;
import com.perceptivesoftware.licensing.client.dialogs.useradmin.plugin.user.UserNavItem;
import com.perceptivesoftware.licensing.client.dto.PermissionsDTO;
import com.perceptivesoftware.licensing.client.dto.SecurityTreeDTO;
import com.perceptivesoftware.licensing.dao.TwRoleprivDaoExt;
import com.perceptivesoftware.licensing.dao.TwRolevalDaoExt;
import com.perceptivesoftware.licensing.dao.TwUserprivDaoExt;
import com.perceptivesoftware.licensing.dao.TwUservalDaoExt;
import com.perceptivesoftware.licensing.domain.generated.TwRolepriv;
import com.perceptivesoftware.licensing.domain.generated.TwRoleprivId;
import com.perceptivesoftware.licensing.domain.generated.TwRoleval;
import com.perceptivesoftware.licensing.domain.generated.TwUserpriv;
import com.perceptivesoftware.licensing.domain.generated.TwUserprivId;
import com.perceptivesoftware.licensing.domain.generated.TwUserval;

@Transactional
@Component
@Service
public class SecurityServiceUtil
{

	private final Log logger = LogFactory.getLog(getClass());

	@Autowired
	private TwUserprivDaoExt nlUserprivDaoExt;
	@Autowired
	private TwUservalDaoExt nlUservalDaoExt;
	@Autowired
	private TwRoleprivDaoExt nlRoleprivDaoExt;
	@Autowired
	private TwRolevalDaoExt nlRolevalDaoExt;

	public void addOrDeletePermissionFromUserPriv(final String userCode, final NPType type, final NPAction action, final String itemCode, final Boolean hasPermission)
	{
		final TwUserprivId kid = new TwUserprivId();
		kid.setUserprivUserCode(userCode);
		kid.setUserprivPrivType(type.getType());
		kid.setUserprivPrivAction(action.getType());
		kid.setUserprivItemCode(itemCode == null ? "0" : itemCode);
		final TwUserpriv findById = nlUserprivDaoExt.findById(kid);

		if (hasPermission) // if adding
		{
			if (findById == null) // if doesn't exist
			{
				final TwUserpriv kup = new TwUserpriv();
				kup.setId(kid);
				nlUserprivDaoExt.save(kup);
			}
		}
		else
		// if deleting
		{
			if (findById != null) // if exists
			{
				nlUserprivDaoExt.delete(findById);
			}
		}
	}

	public void addOrDeletePermissionFromRolePriv(final String roleCode, final NPType type, final NPAction action, final String itemCode, final Boolean hasPermission)
	{
		final TwRoleprivId kid = new TwRoleprivId();
		kid.setRoleprivRoleCode(roleCode);
		kid.setRoleprivPrivType(type.getType());
		kid.setRoleprivPrivAction(action.getType());
		kid.setRoleprivItemCode(itemCode == null ? "0" : itemCode);
		final TwRolepriv findById = nlRoleprivDaoExt.findById(kid);

		if (hasPermission) // if adding
		{
			if (findById == null) // if doesn't exist
			{
				final TwRolepriv kup = new TwRolepriv();
				kup.setId(kid);
				nlRoleprivDaoExt.save(kup);
			}
		}
		else
		// if deleting
		{
			if (findById != null) // if exists
			{
				nlRoleprivDaoExt.delete(findById);
			}
		}
	}

	/**
	 * Get the user permissions and the assigned workspace with its headers and connection groups.
	 * 
	 * @param userval
	 * @return
	 */
	public PermissionsDTO getPermissionsDTOForUserval(final TwUserval userval)
	{
		final PermissionsDTO permissionsDTO = new PermissionsDTO();
		/*
		 * Creating a list for workspaces but it will only have one item - the workspace assigned to this user.
		 */
		/* Get user privs and the assigned workspace. */
		for (final TwUserpriv priv : nlUserprivDaoExt.findByUserId(userval.getUservalId()))
		{
			logger.debug("*** usercode: " + priv.getTwUserval().getUservalId() + ", Type: " + priv.getId().getUserprivPrivType() + ", Action: " + priv.getId().getUserprivPrivAction());
			permissionsDTO.addPermission(new PerceptivePermission(NPType.getEnumForType(priv.getId().getUserprivPrivType()), NPAction.getEnumForAction(priv.getId().getUserprivPrivAction()), priv.getId().getUserprivItemCode(), true));
		}

		return permissionsDTO;
	}

	public PermissionsDTO getPermissionsDTOForRoleval(final TwRoleval roleval)
	{
		final PermissionsDTO permissionsDTO = new PermissionsDTO();

		for (final TwRolepriv priv : nlRoleprivDaoExt.findByRoleId(roleval.getRolevalRoleCode()))
		{
			permissionsDTO.addPermission(new PerceptivePermission(NPType.getEnumForType(priv.getId().getRoleprivPrivType()), NPAction.getEnumForAction(priv.getId().getRoleprivPrivAction()), priv.getId().getRoleprivItemCode(), true));
		}

		return permissionsDTO;
	}

	public PerceptivePermissions getPermissionsForUserval(final TwUserval userval)
	{
		final PerceptivePermissions ret = new PerceptivePermissions();
		for (final TwUserpriv priv : nlUserprivDaoExt.findByUserId(userval.getUservalId()))
		{
			ret.addPermission(new PerceptivePermission(NPType.getEnumForType(priv.getId().getUserprivPrivType()), NPAction.getEnumForAction(priv.getId().getUserprivPrivAction()), priv.getId().getUserprivItemCode(), true));
		}
		ret.setSuperAdmin(Utils.isY(userval.getUservalSuper()));
		return ret;
	}

	public boolean hasPermission(TwUserval userval, PerceptivePermission permission)
	{
		return getPermissionsForUserval(userval).hasPermission(permission);
	}

	public ArrayList<RoleNavItem> getAllRolesAsNavItems()
	{
		final ArrayList<RoleNavItem> roles = new ArrayList<RoleNavItem>();
		final List<TwRoleval> rolevals = nlRolevalDaoExt.getNotDeletedRolevals();
		for (final TwRoleval roleval : rolevals)
		{
			roles.add(new RoleNavItem(roleval.getRolevalRoleName(), roleval.getRolevalRoleCode()));
		}
		Collections.sort(roles);
		return roles;
	}

	public ArrayList<UserNavItem> getAllUsersAsNavItems()
	{
		final ArrayList<UserNavItem> users = new ArrayList<UserNavItem>();
		final List<TwUserval> uservals = nlUservalDaoExt.getNotDeletedUservals();
		for (final TwUserval userval : uservals)
		{
			users.add(new UserNavItem(userval.getUservalUserName(), userval.getUservalId(), userval.getTwRoleval() == null ? null : userval.getTwRoleval().getRolevalRoleCode(), Utils.isY(userval.getUservalSuper())));
		}
		Collections.sort(users);
		return users;
	}

	@Transactional
	public SecurityTreeDTO getSecurityTreeDTO(String roleValCode)
	{
		final SecurityTreeDTO treedto = new SecurityTreeDTO();
		treedto.setUsers(getAllUsersAsNavItems());
		treedto.setRoles(getAllRolesAsNavItems());
		return treedto;
	}
}